Pektis = function(props) {
	this.peparam = {};
	this.profinfo = {};
	this.sxesi = {};
	globals.initObject(this, props);
}

Pektis.prototype.loginGet = function() {
	return this.login;
}

Pektis.prototype.egrafiGet = function() {
	return this.egrafi;
}

Pektis.prototype.onomaGet = function() {
	return this.onoma;
}

Pektis.prototype.emailGet = function() {
	return this.email;
}

Pektis.prototype.pollGet = function() {
	return this.poll;
}

Pektis.prototype.peparamSet = function(peparam) {
	this.peparam[peparam.param] = peparam;
	return this;
}

Pektis.prototype.peparamGet = function(param) {
	return this.peparam[param];
}

Pektis.prototype.peparamWalk = function(callback) {
	globals.walk(this.peparam, callback);
	return this;
}

Pektis.prototype.profinfoSet = function(profinfo) {
	this.profinfo[profinfo.sxoliastis] = profinfo;
	return this;
}

Pektis.prototype.profinfoGet = function(sxoliastis) {
	return this.profinfo[sxoliastis];
}

Pektis.prototype.profinfoWalk = function(callback) {
	globals.walk(this.profinfo, callback);
	return this;
}

Pektis.prototype.sxesiSet = function(sxesi) {
	this.sxesi[sxesi.sxetizomenos] = sxesi;
	return this;
}

Pektis.prototype.sxesiDelete = function(sxetizomenos) {
	delete this.sxesi[sxetizomenos];
	return this;
}

Pektis.prototype.sxesiGet = function(sxetizomenos) {
	return this.sxesi[sxetizomenos];
}

Pektis.prototype.sxesiWalk = function(callback) {
	globals.walk(this.sxesi, callback);
	return this;
}

Pektis.prototype.isFilos = function(pektis) {
	var sxesi = this.sxesiGet(pektis);
	if (!sxesi) return false;
	return sxesi.isFilos();
}

Pektis.prototype.isApoklismenos = function(pektis) {
	var sxesi = this.sxesiGet(pektis);
	if (!sxesi) return false;
	return sxesi.isApoklismenos();
}

Pektis.prototype.isAsxetos = function(pektis) {
	return !this.sxesiGet(pektis);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Peparam = function(props) {
	globals.initObject(this, props);
}

Peparam.prototype.pektisGet = function() {
	return this.pektis;
}

Peparam.prototype.paramGet = function() {
	return this.param;
}

Peparam.prototype.timiGet = function() {
	return this.timi;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Profinfo = function(props) {
	globals.initObject(this, props);
}

Profinfo.prototype.pektisGet = function() {
	return this.pektis;
}

Profinfo.prototype.sxoliastisGet = function() {
	return this.sxoliastis;
}

Profinfo.prototype.kimenoGet = function() {
	return this.kimeno;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Sxesi = function(props) {
	globals.initObject(this, props);
}

Sxesi.prototype.pektisGet = function() {
	return this.pektis;
}

Sxesi.prototype.sxetizomenosGet = function() {
	return this.sxetizomenos;
}

Sxesi.prototype.sxesiGet = function() {
	return this.sxesi;
}

Sxesi.prototype.isFilos = function() {
	return(this.sxesi == 'ΦΙΛΟΣ');
}

Sxesi.prototype.isApoklismenos = function() {
	return(this.sxesi == 'ΑΠΟΚΛΕΙΣΜΕΝΟΣ');
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Sinedria = function(props) {
	var skiniko;

	if (props) {
		skiniko = props.skiniko;
		delete props.skiniko;
	}
	else skiniko = undefined;

	globals.initObject(this, props);

	if (skiniko) props.skiniko = skiniko;
}

Sinedria.prototype.skinikoFetch = function() {
	if (this.hasOwnProperty('skiniko')) return this.skiniko;
	globals.fatal('απροσδιόριστο σκηνικό συνεδρίας');
}

Sinedria.prototype.pektisGet = function() {
	return this.pektis;
}

Sinedria.prototype.klidiGet = function() {
	return this.klidi;
}

Sinedria.prototype.ipGet = function() {
	return this.ip;
}

Sinedria.prototype.isodosGet = function() {
	return this.isodos;
}

Sinedria.prototype.pollGet = function() {
	return this.poll;
}

Sinedria.prototype.trapeziGet = function() {
	return this.trapezi;
}

Sinedria.prototype.oxiTrapezi = function() {
	return !this.trapeziGet();
}

Sinedria.prototype.thesiGet = function() {
	return this.thesi;
}

Sinedria.prototype.oxiThesi = function() {
	return !this.thesiGet();
}

Sinedria.prototype.simetoxiGet = function() {
	return this.simetoxi;
}

Sinedria.prototype.setRebelos = function() {
	delete this.trapezi;
	delete this.thesi;
	delete this.simetoxi;
	return this;
}

Sinedria.prototype.oxiRebelos = function() {
	return this.trapeziGet();
}

Sinedria.prototype.isRebelos = function() {
	return !this.oxiRebelos();
}

Sinedria.prototype.isPektis = function() {
	return(this.simetoxiGet() == 'ΠΑΙΚΤΗΣ');
}

Sinedria.prototype.oxiPektis = function() {
	return !this.isPektis();
}

Sinedria.prototype.setPektis = function(trapezi, thesi) {
	this.trapeziSet(trapezi);
	this.simetoxiSet('ΠΑΙΚΤΗΣ');
	this.thesiSet(thesi);
	return this;
}

Sinedria.prototype.isTheatis = function() {
	return(this.simetoxiGet() == 'ΘΕΑΤΗΣ');
}

Sinedria.prototype.oxiTheatis = function() {
	return !this.isTheatis();
}

Sinedria.prototype.setTheatis = function(trapezi, thesi) {
	this.trapeziSet(trapezi);
	this.simetoxiSet('ΘΕΑΤΗΣ');
	this.thesiSet(thesi);
	return this;
}

Sinedria.prototype.trapeziSet = function(trapezi) {
	this.trapezi = trapezi;
	return this;
}

Sinedria.prototype.simetoxiSet = function(simetoxi) {
	this.simetoxi = simetoxi;
	return this;
}

Sinedria.prototype.thesiSet = function(thesi) {
	this.thesi = thesi;
	return this;
}

Sinedria.prototype.isTrapezi = function(trapezi) {
	return(this.hasOwnProperty('trapezi') && (this.trapeziGet() == trapezi));
}

Sinedria.prototype.alloTrapezi = function(trapezi) {
	return !this.isTrapezi(trapezi);
}

Sinedria.prototype.pektisTheatis = function() {
	var skiniko = this.skinikoFetch(), pektis, trapezi, thesi;

	trapezi = this.trapeziGet();
	if (!trapezi) return this;

	trapezi = skiniko.trapeziGet(this.trapeziGet());
	if (!trapezi) return this;

	pektis = this.pektisGet();
	thesi = this.thesi;

	// Αν ο παίκτης μετέχει ως παίκτης στο τραπέζι, τον καθιστώ θεατή
	// στην ίδια θέση.

	if (this.isPektis()) {
		// Κρατάμε αρχείο ότι ο παίκτης κατείχε τη θέση ως παίκτης
		// πριν εκκενώσουμε τη συγκεκριμένη θέση.

		trapezi.pektis[thesi] = pektis;
		delete trapezi['pektis' + thesi];

		this.simetoxi = 'ΘΕΑΤΗΣ';
		trapezi.theatisAdd(new Theatis({
			pektis: pektis,
			thesi: thesi,
		}));

		return this;
	}

	// Ο παίκτης δεν μετέχει ως παίκτης, άρα πρέπει να μετέχει ως θεατής.

	if (this.oxiTheatis()) return this;

	// Αν η θέση στην οποία παρακολουθεί είναι κατειλημμένη, δεν μπορεί
	// να γίνει η αλλαγή ρόλου.

	if (trapezi.pektisGet(thesi)) return this;

	// Εγκαθιστώ τον παίκτη ως παίκτη στη συγκεκριμένη θέση.

	this.simetoxi = 'ΠΑΙΚΤΗΣ';
	trapezi.
	theatisDelete(pektis).
	pektisSet(pektis, thesi);

	return this;
}

Sinedria.prototype.thesiRoloi = function() {
	var skiniko = this.skinikoFetch(), trapezi, thesiPrin, thesiMeta, pektis;

	trapezi = skiniko.trapeziGet(this.trapeziGet());
	if (!trapezi) return this;

	thesiPrin = this.thesiGet();
	if (!thesiPrin) return this;

	thesiMeta = trapezi.keniThesi(thesiPrin);
	if (!thesiMeta) return this;

	this.thesiSet(thesiMeta);

	pektis = this.pektisGet();
	trapezi.
	pektisDelete(thesiPrin).
	pektisSet(pektis, thesiMeta);

	delete trapezi.pektis[thesiPrin];
	trapezi.pektis[thesiMeta] = pektis;
	trapezi.thesi[pektis] = thesiMeta;

	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η μέθοδος "thesiCheck" ελέγχει και διορθώνει τα στοιχεία θέσης τής συνεδρίας σε συνδυασμό με
// τα στοιχεία των τραπεζιών (παίκτες/θεατές). Προτεραιότητα δίνεται στα στοιχεία της ίδιας της
// συνεδρίας, δηλαδή αν τα στοιχεία θέσης της συνεδρίας είναι συμπληρωμένα, ελέγχονται και μόνον
// εφόσον αυτά δεν είναι ορθά, η συνεδρία επανεντοπίζεται με βάση τα στοιχεία του σκηνικού. Πάντως,
// σε κάθε περίπτωση γίνεται και διόρθωση των στοιχείων του σκηνικού όσον αφορά στη συγκεκριμένη
// συνεδρία.

Sinedria.prototype.thesiCheck = function() {
	var skiniko = this.skinikoFetch(), kodikos, trapezi, pektis, thesi;

	// Αν δεν έχουμε τραπέζι στα στοιχεία θέσης, εντοπίζουμε τώρα.

	kodikos = this.trapeziGet();
	if (!kodikos) return this.entopismos();

	// Βρέθηκε τραπέζι στα στοιχεία θέσης της συνεδρίας και ελέγχουμε την ύπαρξη του
	// τραπεζιού στο σκηνικό.

	trapezi = skiniko.trapeziGet(kodikos);
	if (!trapezi) return this.entopismos();

	// Η συνεδρία εμπλέκεται σε υπαρκτό τραπέζι του σκηνικού. Αν ο παίκτης είναι παίκτης
	// του τραπεζιού, τότε τίθενται ανάλογα τα στοιχεία θέσης τού παίκτη.

	pektis = this.pektisGet();		// τό login name του παίκτη της συνεδρίας
	thesi = trapezi.thesiPekti(pektis);	// η θέση τού παίκτη ως παίκτη στο τραπέζι
	if (thesi) {
		skiniko.theatisDelete(pektis).rebelosDelete(pektis);
		return this.setPektis(kodikos, thesi);
	}

	// Ο παίκτης δεν κατέχει θέση ως παίκτης στο τραπέζι. Αν η συνεδρία δεν είναι συνεδρία
	// θεατού, τα στοιχεία θέσης θεωρούνται λανθασμένα και επανεντοπίζουμε τώρα.

	if (this.oxiTheatis()) return this.entopismos();

	// Η συνεδρία φαίνεται να είναι συνεδρία θεατού και το μόνο που έμεινε να ελεγχθεί
	// είναι η εγκυρότητα τής θέσης.

	thesi = this.thesiGet();
	if (geister.oxiThesi(thesi)) return this.entopismos();

	// Υπάρχει τραπέζι, η θέση είναι έγκυρη και η συνεδρία είναι συνεδρία θεατού, άρα
	// πρέπει να προσθέσουμε τον παίκτη ως θεατή στη λίστα θεατών τού τραπεζιού. Καλού
	// κακού κάνουμε πρώτα εκκαθάριση θεατών και περιφερομένων όσον αφορά στον παίκτη
	// της ανά χείρας συνεδρίας.

	skiniko.theatisDelete(pektis).rebelosDelete(pektis);
	trapezi.theatisAdd(new Theatis({
		pektis: pektis,
		thesi: thesi,
	}));

	return this;
}

// Η μέθοδος "entopismos" δέχεται ως παράμετρο ένα σκηνικό, επιχειρεί να εντοπίσει την ανά
// χείρας συνεδρία σε αυτό το σκηνικό και να συμπληρώσει τα στοιχεία θέσης της συνεδρίας.
// Αν δεν δοθεί σκηνικό, χρησιμοποιείται το σκηνικό στο οποίο είναι ενταγμένη η συνεδρία.
// Προτεραιότητα έχει ο εντοπισμός ως θεατού, ενώ αν εντοπιστεί ο παίκτης σε περισσότερα
// από ένα τραπέζια, προτιμάται το νεότερο.

Sinedria.prototype.entopismos = function(skiniko) {
	var pektis = this.pektisGet(), found = 0, sinedria = this;

	if (!skiniko) skiniko = this.skinikoFetch();
	skiniko.trapeziWalk(function(kodikos, trapezi) {
		var theatis = trapezi.theatisGet(pektis);
		if (!theatis) return;
		if (kodikos < found) return;
		sinedria.setTheatis(found = kodikos, theatis.thesi);
	});

	if (found) {
		skiniko.theatisDelete(pektis, found).rebelosDelete(pektis);
		return this;
	}

	skiniko.theatisDelete(pektis).trapeziWalk(function(kodikos, trapezi) {
		var thesi = trapezi.thesiPekti(pektis);
		if (!thesi) return;
		if (kodikos < found) return;
		sinedria.setPektis(found = kodikos, thesi);
	});

	if (found) skiniko.rebelosDelete(pektis);
	else {
		this.setRebelos();
		skiniko.rebelosAdd(new Rebelos({
			pektis: this.pektis,
		}));
	}

	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Rebelos = function(props) {
	globals.initObject(this, props);
}

Rebelos.prototype.skinikoFetch = function() {
	if (this.hasOwnProperty('skiniko')) return this.skiniko;
	globals.fatal('απροσδιόριστο σκηνικό περιφερομένου');
}

Rebelos.prototype.pektisGet = function() {
	return this.pektis;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Trapezi = function(props) {
	var skiniko, tablo;

	if (props) {
		skiniko = props.skiniko;
		delete props.skiniko;
		tablo = props.tablo;
		delete props.tablo;
	}
	else {
		skiniko = undefined;
		tablo = undefined;
	}

	this.trparam = {};
	this.prosklisi = {};
	this.kalesmenos = {};
	this.partida = [];
	this.theatis = {};
	this.sizitisi = [];
	this.thesi = {};
	this.pektis = {};

	globals.initObject(this, props);

	if (skiniko) props.skiniko = skiniko;
	if (tablo) props.tablo = tablo;
}

Trapezi.prototype.skinikoFetch = function() {
	if (this.hasOwnProperty('skiniko')) return this.skiniko;
	globals.fatal('απροσδιόριστο σκηνικό τραπεζιού');
}

Trapezi.prototype.kodikosSet = function(kodikos) {
	this.kodikos = parseInt(kodikos);
	return this;
}

Trapezi.prototype.kodikosGet = function() {
	return this.kodikos;
}

Trapezi.prototype.stisimoSet = function(stisimo) {
	this.stisimo = parseInt(stisimo);
	return this;
}

Trapezi.prototype.stisimoGet = function() {
	return this.stisimo;
}

Trapezi.prototype.pektisSet = function(pektis, thesi) {
	this['pektis' + thesi] = pektis;
	return this;
}

Trapezi.prototype.pektisDelete = function(thesi) {
	delete this['pektis' + thesi];
	return this;
}

Trapezi.prototype.pektisGet = function(thesi) {
	return this['pektis' + thesi];
}

Trapezi.prototype.thesiPekti = function(pektis) {
	var thesi;

	for (thesi = 1; thesi <= geister.thesiMax; thesi++) {
		if (this.pektisGet(thesi) == pektis) return thesi;
	}

	return null;
}

Trapezi.prototype.apodoxiSet = function(apodoxi, thesi) {
	if (thesi !== undefined) {
		this['apodoxi' + thesi] = apodoxi;
		return this;
	}

	for (thesi = 1; thesi <= geister.thesiMax; thesi++) {
		this.apodoxiSet(apodoxi, thesi);
	}
	return this;
}

Trapezi.prototype.apodoxiGet = function(thesi) {
	return this['apodoxi' + thesi];
}

Trapezi.prototype.isApodoxi = function(thesi) {
	return this.apodoxiGet(thesi).isNai();
}

Trapezi.prototype.oxiApodoxi = function(thesi) {
	return !this.apodoxiGet(thesi).isNai();
}

Trapezi.prototype.pollSet = function(poll) {
	this.poll = parseInt(poll);
	return this;
}

Trapezi.prototype.pollGet = function() {
	return this.poll;
}

Trapezi.prototype.arxioGet = function() {
	return this.arxio;
}

Trapezi.prototype.trparamSet = function(trparam) {
	this.trparam[trparam.param] = trparam;
	return this;
}

Trapezi.prototype.trparamGet = function(param) {
	return this.trparam[param];
}

Trapezi.prototype.trparamWalk = function(callback) {
	globals.walk(this.trparam, callback);
	return this;
}

Trapezi.prototype.isKalesmenos = function(pektis) {
	return this.kalesmenos[pektis];
}

Trapezi.prototype.oxiKalesmenos = function(pektis) {
	return !this.iskalesmenos(pektis);
}

Trapezi.prototype.kalesmenosCheck = function(pektis) {
	var i;

	for (i in this.prosklisi) {
		if (this.prosklisi[i].prosGet() != pektis) continue;
		this.kalesmenos[pektis] = true;
		return this;
	}

	delete this.kalesmenos[pektis];
	return this;
}

Trapezi.prototype.prosklisiGet = function(kodikos) {
	return this.prosklisi[kodikos];
}

Trapezi.prototype.prosklisiAdd = function(prosklisi) {
	this.prosklisi[prosklisi.kodikosGet()] = prosklisi;
	this.kalesmenos[prosklisi.prosGet()] = true;
	return this;
}

Trapezi.prototype.prosklisiDelete = function(kodikos) {
	var prosklisi = this.prosklisiGet(kodikos);
	if (!prosklisi) return this;

	delete this.prosklisi[kodikos];
	this.kalesmenosCheck(prosklisi.prosGet());
	return this;
}

Trapezi.prototype.prosklisiWalk = function(callback) {
	globals.walk(this.prosklisi, callback);
	return this;
}

Trapezi.prototype.theatisAdd = function() {
	var theatis;

	if (typeof arguments[0] == 'object') theatis = arguments[0];
	else theatis = new Theatis({
		pektis: arguments[0],
		thesi: arguments[1],
	});

	this.theatis[theatis.pektisGet()] = theatis;
	return this;
}

Trapezi.prototype.theatisGet = function(login) {
	return this.theatis[login];
}

Trapezi.prototype.theatisDelete = function(login) {
	var theatis = this.theatisGet(login);
	if (!theatis) return this;

	this.thesi[login] = theatis.thesi;
	delete this.theatis[login];

	return this;
}

Trapezi.prototype.theatisWalk = function(callback) {
	globals.walk(this.theatis, callback);
	return this;
}

Trapezi.prototype.partidaAdd = function(partida) {
	this.partida.push(partida);
	return this;
}

Trapezi.prototype.partidaGet = function(i) {
	if (i === undefined) {
		i = this.partida.length - 1;
		if (i < 0) return null;
	}

	return this.partida[i];
}

Trapezi.prototype.partidaWalk = function(callback) {
	var i;
	for (i = 0; i < this.partida.length; i++) {
		if (callback) callback(i, this.partidaGet(i));
	}
	return this;
}

Trapezi.prototype.sizitisiAdd = function(sizitisi) {
	this.sizitisi.push(sizitisi);
	return this;
}

Trapezi.prototype.sizitisiGet = function(i) {
	return this.sizitisi[i];
}

Trapezi.prototype.sizitisiWalk = function(callback) {
	var i;
	for (i = 0; i < this.sizitisi.length; i++) {
		if (callback) callback(i, this.sizitisiGet(i));
	}
	return this;
}

Trapezi.prototype.thesiWalk = function(callback) {
	var i;
	for (i = 1; i <= geister.thesiMax; i++) {
		if (callback) callback(i, this);
	}
	return this;
}

Trapezi.prototype.trapeziAdd = function(skiniko) {
	skiniko.trapeziAdd(this);
	return this;
}

Trapezi.prototype.exodosPekti = function(pektis) {
	var thesi = this.thesiPekti(pektis);
	if (!thesi) return this;

	this.thesi[pektis] = thesi;
	this.pektis[thesi] = pektis;
	delete this['pektis' + thesi];

	return this;
}

Trapezi.prototype.telefteosPektis = function(thesi) {
	return this.pektis[thesi];
}

Trapezi.prototype.protasiThesis = function(pektis) {
	return this.thesi.hasOwnProperty(pektis) ? this.thesi[pektis] : 1;
}

Trapezi.prototype.keniThesi = function(meta) {
	var thesi;

	if (meta === undefined) meta = 0;
	for (thesi = meta + 1; thesi <= geister.thesiMax; thesi++) {
		if (!this.pektisGet(thesi)) return thesi;
	}

	for (thesi = 1; thesi < meta; thesi++) {
		if (!this.pektisGet(thesi)) return thesi;
	}

	return null;
}

Trapezi.prototype.tabloGet = function() {
	if (this.hasOwnProperty('tablo')) return this.tablo;

	this.tablo = new Tablo({
		trapezi: this,
	});
	return this.tablo;
}

Trapezi.prototype.apodoxes = function(nai) {
	var thesi;

	if (nai === undefined) nai = 0;
	for (thesi in geister.validThesi) {
		this.apodoxiGet(thesi).isNai() && nai++;
	}

	return nai;
}

// Η μέθοδος "skor" καταμετρά σε πόσες παρτίδες του τραπεζιού έχει νικήσει ο παίκτης
// του οποίου το login name περνάμε ως παράμετρο. Αν δεν περάσουμε όνομα παίκτη,
// επιστρέφεται το πλήθος των τελειωμένων παρτίδων, δηλαδή των παρτίδων που έχουν
// νικητή.

Trapezi.prototype.skor = function(pektis) {
	var nikitis, count = 0, skor = 0;

	this.partidaWalk(function(i, partida) {
		nikitis = partida.nikitisGet();
		if (!nikitis) return;

		count++;
		if (nikitis == pektis) skor++;
	});

	return pektis ? skor : count;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Trparam = function(props) {
	globals.initObject(this, props);
}

Trparam.prototype.trapeziGet = function() {
	return this.trapezi;
}

Trparam.prototype.paramGet = function() {
	return this.param;
}

Trparam.prototype.timiGet = function() {
	return this.timi;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Prosklisi = function(props) {
	globals.initObject(this, props);
}

Prosklisi.prototype.kodikosSet = function(kodikos) {
	this.kodikos = parseInt(kodikos);
	return this;
}

Prosklisi.prototype.kodikosGet = function() {
	return this.kodikos;
}

Prosklisi.prototype.trapeziGet = function() {
	return this.trapezi;
}

Prosklisi.prototype.apoSet = function(pektis) {
	this.apo = pektis;
	return this;
}

Prosklisi.prototype.apoGet = function() {
	return this.apo;
}

Prosklisi.prototype.prosSet = function(pektis) {
	this.pros = pektis;
	return this;
}

Prosklisi.prototype.prosGet = function() {
	return this.pros;
}

Prosklisi.prototype.epidosiSet = function(epidosi) {
	this.epidosi = parseInt(epidosi);
	return this;
}

Prosklisi.prototype.epidosiGet = function() {
	return this.epidosi;
}

Prosklisi.prototype.prosklisiAdd = function(trapezi) {
	trapezi.prosklisiAdd(this);
	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Partida = function(props) {
	this.energia = [];
	globals.initObject(this, props);
}

Partida.prototype.kodikosGet = function() {
	return this.kodikos;
}

Partida.prototype.trapeziGet = function() {
	return this.trapezi;
}

Partida.prototype.enarxiGet = function() {
	return this.enarxi;
}

Partida.prototype.protosGet = function() {
	return this.protos;
}

Partida.prototype.nikitisGet = function() {
	return this.nikitis;
}

Partida.prototype.telosGet = function() {
	return this.telos;
}

Partida.prototype.energiaAdd = function(energia) {
	this.energia.push(energia);
	return this;
}

Partida.prototype.energiaGet = function(i) {
	return this.energia[i];
}

Partida.prototype.energiaWalk = function(callback) {
	var i;
	for (i = 0; i < this.energia.length; i++) {
		if (callback) callback(i, this.energiaGet(i));
	}

	return this;
}

Partida.prototype.telosSet = function(nikitis) {
	this.nikitis = nikitis;
	this.telos = globals.toraServer();
	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Energia = function(props) {
	globals.initObject(this, props);
}

Energia.prototype.kodikosSet = function(kodikos) {
	this.kodikos = kodikos;
	return this;
}

Energia.prototype.kodikosGet = function() {
	return this.kodikos;
}

Energia.prototype.partidaGet = function() {
	return this.partida;
}

Energia.prototype.pektisGet = function() {
	return this.pektis;
}

Energia.prototype.idosGet = function() {
	return this.idos;
}

Energia.prototype.dataGet = function() {
	return this.data;
}

Energia.prototype.dataSet = function(data) {
	this.data = data;
	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Theatis = function(props) {
	globals.initObject(this, props);
}

Theatis.prototype.pektisGet = function() {
	return this.pektis;
}

Theatis.prototype.thesiGet = function() {
	return this.thesi;
}

Theatis.prototype.thesiSet = function(thesi) {
	this.thesi = thesi;
	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Sizitisi = function(props) {
	globals.initObject(this, props);
}

Sizitisi.prototype.trapeziGet = function() {
	return this.trapezi;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Skiniko = function(props) {
	this.skinikoReset();
	globals.initObject(this, props);
}

Skiniko.prototype.skinikoReset = function() {
	this.pektis = {};
	this.trapezi = {};
	this.sinedria = {};
	this.rebelos = {};
	this.sizitisi = [];

	return this;
}

Skiniko.prototype.pektisAdd = function(pektis) {
	this.pektis[pektis.loginGet()] = pektis;
	return this;
}

Skiniko.prototype.pektisWalk = function(callback) {
	globals.walk(this.pektis, callback);
	return this;
}

Skiniko.prototype.pektisGet = function(login) {
	return this.pektis[login];
}

Skiniko.prototype.oxiPektis = function(login) {
	return !this.pektisGet(login);
}

Skiniko.prototype.sinedriaAdd = function(sinedria) {
	this.sinedria[sinedria.pektisGet()] = sinedria;
	sinedria.skiniko = this;
	return this;
}

Skiniko.prototype.sinedriaDelete = function(login) {
	delete this.sinedria[login];
	return this;
}

Skiniko.prototype.sinedriaWalk = function(callback) {
	globals.walk(this.sinedria, callback);
	return this;
}

Skiniko.prototype.sinedriaGet = function(login) {
	return this.sinedria[login];
}

Skiniko.prototype.isSinedria = function(login) {
	return this.sinedriaGet(login);
}

Skiniko.prototype.oxiSinedria = function(login) {
	return !this.sinedriaGet(login);
}

Skiniko.prototype.trapeziAdd = function(trapezi) {
	this.trapezi[trapezi.kodikosGet()] = trapezi;
	trapezi.skiniko = this;
	return this;
}

Skiniko.prototype.trapeziDelete = function(kodikos) {
	delete this.trapezi[kodikos];
	return this;
}

// Η μέθοδος "trapeziWalk" διατρέχει τα τραπέζια του σκηνικού και για κάθε τραπέζι
// καλεί callback function με παραμέτρους τον κωδικό τραπεζιού και το ίδιο το
// τραπέζι. Καταφεύγουμε σε adhoc επίσκεψη για να έχουμε τον κωδικό ως αριθμό και
// όχι ως string μέσα στην callback.

Skiniko.prototype.trapeziWalk = function(callback) {
	var kodikos;

	for (kodikos in this.trapezi) {
		callback(parseInt(kodikos), this.trapezi[kodikos]);
	}

	return this;
}

Skiniko.prototype.trapeziGet = function(kodikos) {
	return this.trapezi[kodikos];
}

Skiniko.prototype.trapeziFetch = function(kodikos) {
	var trapezi = this.trapeziGet(kodikos);
	if (trapezi) return trapezi;
	globals.fatal('δεν βρέθηκε το τραπέζι');
}

Skiniko.prototype.oxiTrapezi = function(kodikos) {
	return !this.trapeziGet(kodikos);
}

Skiniko.prototype.rebelosAdd = function(rebelos) {
	this.rebelos[rebelos.pektisGet()] = rebelos;
	rebelos.skiniko = this;
	return this;
}

Skiniko.prototype.rebelosDelete = function(login) {
	delete this.rebelos[login];
	return this;
}

Skiniko.prototype.rebelosWalk = function(callback) {
	globals.walk(this.rebelos, callback);
	return this;
}

Skiniko.prototype.rebelosGet = function(login) {
	return this.rebelos[login];
}

Skiniko.prototype.oxiRebelos = function(login) {
	return !this.rebelosGet(login);
}

Skiniko.prototype.sizitisiAdd = function(sizitisi) {
	if (this.sizitisi.push(sizitisi) < geister.sxolioMax) return this;
	this.sizitisi.splice(0, geister.sxolioMin);
	return this;
}

Skiniko.prototype.sizitisiWalk = function(callback) {
	var i;
	for (i = 0; i < this.sizitisi.length; i++) {
		callback(i, this.sizitisi[i]);
	}
	return this;
}

// Η μέθοδος "theatisDelete" διατρέχει όλα τα τραπέζια του σκηνικού και διαγράφει
// από τη λίστα θεατών τον παίκτη του οποίου το login περνάμε ως πρώτη παράμετρο.
// Μπορούμε να περάσουμε ως δεύτερη παράμετρο τον κωδικό τραπεζιού το οποίο θα
// εξαιρεθεί από τη διαδικασία (ενδεχομένως το τραπέζι στο οποίο όντως ο παίκτης
// είναι θεατής).

Skiniko.prototype.theatisDelete = function(login, ektos) {
	return this.trapeziWalk(function(kodikos, trapezi) {
		if (kodikos == ektos) return;
		trapezi.theatisDelete(login);
	});
}

// Η μέθοδος "thesiCheck" διατρέχει τις συνεδρίες τού σκηνικού και ελέγχει/διορθώνει
// τα στοιχεία θέσης κάθε συνεδρίας.

Skiniko.prototype.thesiCheck = function() {
	this.sinedriaWalk(function(login, sinedria) {
		sinedria.thesiCheck();
	});
	return this;
}

Skiniko.prototype.setOpt = function() {
	var i;

	if (!this.hasOwnProperty('opts')) this.opts = {};

	switch (arguments.length) {

	// Αν δοθεί μια μόνο παράμετρος τότε είτε πρόκειται για μαζική ανάθεση τιμών
	// σε πολλές options μέσω λίστας, είτε πρόκειται για όνομα συγκεκριμένης
	// option προς απαλοιφή.

	case 1:
		if (typeof arguments[0] === 'object') {
			for (i in arguments[0]) {
				this.setOpt(i, arguments[0][i]);
			}
		}
		else delete this.opts[arguments[0]];
		break;

	// Αν έχουν δοθεί δύο παράμετροι, τότε πρόκειται για όνομα και τιμή συγκεκριμένης
	// option τού σκηνικού.

	case 2:
		this.opts[arguments[0]] = arguments[1];
		break;

	default:
		globals.fatal('invalid "skiniko" options');
	}

	return this;
}

Skiniko.prototype.getOpt = function(option) {
	if (!this.hasOwnProperty('opts')) this.opts = {};
	return this.opts[option];
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Για να δημιουργήσουμε αντικείμενο κίνησης χρησιμοποιούμε constructor παρόμοιο
// με όλα τα υπόλοιπα αντικείμενα της εφαρμογής. Μπορούμε, όμως, εναλλακτικά να
// χρησιμοποιήσουμε τον constructor με παράμετρο το είδος της κίνησης, π.χ.
//
//	k = new Kinisi('PK');
//
// και σε συνδυασμό με τη μέθοδο "set" (βλ. παρακάτω) να έχουμε κατασκευές της
// μορφής:
//
//	k = new Kinisi('PK').set({
//		p: new Pektis(p).incognito(),
//	});

Kinisi = function(arg) {
	if (typeof arg == 'string') this.idosSet(arg);
	else globals.initObject(this, arg);
}

// Η μέθοδος "set" θέτει properties της κινήσεως, είτε ως μεμονωμένα key/value
// pairs, είτε ως στοιχεία λίστας την οποία περνάμε ως παράμετρο, π.χ.
//
//	k.set('p', new Pektis(p).incognito());
//
// θέτει το property "p" να δείχνει σε αντίγραφο του παίκτη "p" από το οποίο
// αποκόπτουμε ευαίσθητα δεδομένα.
//
//	k.set({
//		p: new Pektis(p).incognito(),
//		w: globals.time(),
//	});
//
// θέτει το property "p" όπως πριν και το property "w" να περιέχει το τρέχον
// timestamp.

Kinisi.prototype.set = function(prop, val) {
	if (typeof prop == 'string') this[prop] = val;
	else for (val in prop) this[val] = prop[val];
	return this;
}

Kinisi.prototype.get = function(prop) {
	return this[prop];
}

Kinisi.prototype.fetch = function(prop) {
	if (!this.hasOwnProperty(prop)) globals.fatal(prop + ': ακαθόριστη property κίνησης');
	return this.get(prop);
}

Kinisi.prototype.idosSet = function(idos) {
	this.set('?', idos);
}

Kinisi.prototype.idosGet = function() {
	return this.get('?');
}

Kinisi.prototype.idosFetch = function() {
	if (!this.hasOwnProperty('?')) globals.fatal('ακαθόριστο είδος κίνησης');
	return this.idosGet();
}

Kinisi.prototype.isProp = function(prop) {
	return this.hasOwnProperty(prop);
}

Kinisi.prototype.delProp = function(prop) {
	delete this[prop];
	return this;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Skiniko.prototype.skiniko2object = function() {
	var skiniko = this, i;

	for (i in this.pektis) {
		this.pektis[i] = new Pektis(this.pektis[i]).pektis2object();
	}

	for (i in this.trapezi) {
		this.trapezi[i] = new Trapezi(this.trapezi[i]).trapezi2object();
		this.trapezi[i].skiniko = skiniko;
	}
	for (i in this.sinedria) {
		this.sinedria[i] = new Sinedria(this.sinedria[i]);
		this.sinedria[i].skiniko = skiniko;
	}

	for (i in this.rebelos) {
		this.rebelos[i] = new Rebelos(this.rebelos[i]);
		this.rebelos[i].skiniko = skiniko;
	}

	for (i in this.sizitisi) {
		this.sizitisi[i] = new Sizitisi(this.sizitisi[i]);
	}

	return this;
}

Pektis.prototype.pektis2object = function() {
	var i;
	for (i in this.peparam) this.peparam[i] = new Peparam(this.peparam[i]);
	for (i in this.profinfo) this.profinfo[i] = new Profinfo(this.profinfo[i]);
	for (i in this.sxesi) this.sxesi[i] = new Sxesi(this.sxesi[i]);
	return this;
}

Trapezi.prototype.trapezi2object = function() {
	var i;
	for (i in this.trparam) this.trparam[i] = new Trparam(this.trparam[i]);
	for (i in this.prosklisi) this.prosklisi[i] = new Prosklisi(this.prosklisi[i]);
	for (i in this.partida) this.partida[i] = new Partida(this.partida[i]).partida2object();
	for (i in this.theatis) this.theatis[i] = new Theatis(this.theatis[i]);
	for (i in this.sizitisi) this.sizitisi[i] = new Sizitisi(this.sizitisi[i]);
	return this;
}

Partida.prototype.partida2object = function() {
	var i;
	for (i in this.energia) this.energia[i] = new Energia(this.energia[i]);
	return this;
}
